SuperStrict

' Sample actor-based program.
' Actors and thread pools are
' used to run multiple serial
' tasks in parallel.

' Using callbacks.

Framework BRL.StandardIO

Import BRL.Random

Import Otus.Actor

' Thread-safe wrapper for Print
Function Print(s:String="")
	Global mutex:TMutex = CreateMutex()
	mutex.Lock
	BRL.StandardIO.Print s
	mutex.Unlock
End Function

' Callbacks for actors

Function Download:Object(msg:Object)
	Print "Downloading "+msg.ToString()+".tar.gz..."
	Delay Rand(5000)	'Simulate download time
	Print "Downloaded "+msg.ToString()+".tar.gz"
	Return msg
End Function

Function Extract:Object(msg:Object)
	Print "Extracting "+msg.ToString()+".tar.gz..."
	Delay Rand(500)	'Simulate extract time
	Print "Extracted "+msg.ToString()+".tar.gz"
	Return msg
End Function

Function Build:Object(msg:Object)
	Print "Building "+msg.ToString()+".build..."
	Delay Rand(2000)	'Simulate build time
	Print "Built "+msg.ToString()+".build"
	Return msg
End Function

Global cleaned:Int

Function Clean:Object(msg:Object)
	Print "Cleaning "+msg.ToString()+"..."
	Delay 10
	Print "Cleaned "+msg.ToString()
	cleaned :+ 1
	Return Null
End Function

Function Sleep()
	Delay 1
End Function

Print "Creating actors..."


' Create a pool of up to 5 downloader threads
Local downloader:TActor = CreateActorThreadPool(download, 5)

' Create a single extracter thread
Local extracter:TActor = CreateActorThread(extract)

' Create a pool of up to 2 builder threads
Local builder:TActor = CreateActorThreadPool(build, 2)

' Create a cleaner actor without thread
Local cleaner:TActor = CreateActor(clean)


Print "Sending work..."


' Set a list of files to download, extract, build and clean up in order
Local files:String[] = ["file1", "file2", "file3", "file4", "file5", "file6", "file7", "file8"]

For Local file:String = EachIn files
	downloader.Send(file).Chain(extracter).Chain(builder).Chain(cleaner)
Next


' Run the cleaner until all is done
While cleaned < files.length
	cleaner.Process
	Delay 1
Wend


Print "All done."

Delay 1000
